﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using IRC.IRepairClouds.DataLayer;

namespace IRC.IRepairClouds.WebClient
{
    public static class PagesAuthorization
    {
        public enum Pages
        {
            NewCase,
            CaseSearch,
        }

        private static Dictionary<UrlParser, Tuple<AuthRequirements, HashSet<Pages>>> _urlReq = new Dictionary<UrlParser, Tuple<AuthRequirements, HashSet<Pages>>>();
        private static Dictionary<string, Tuple<AuthRequirements, HashSet<Pages>>> _keyReq = new Dictionary<string, Tuple<AuthRequirements, HashSet<Pages>>>();
        private static Dictionary<Pages, AuthRequirements> _pageReq = new Dictionary<Pages, AuthRequirements>();

        private static Dictionary<string, PagesAuthorized> _cached = new Dictionary<string, PagesAuthorized>();

        static PagesAuthorization()
        {
            var csc = new AuthRequirements(EPartnerRole.PartnerRoles.PartnerCoordinator | EPartnerRole.PartnerRoles.Client);
            AddUrl(Pages.NewCase, "~/Cases/NewCase.aspx", csc);
            AddUrl(Pages.CaseSearch, "~/Cases/CaseSearch.aspx", csc);

        }

        #region public properties

        public static void ResetCache()
        {
            lock (_cached)
            {
                _cached.Clear();
            }
        }

        public static PagesAuthorized Authorized
        {
            get
            {
                var login = EUser.Get();
                if (login == null)
                    throw new NotSupportedException("login == null");
                PagesAuthorized cached;
                if (!_cached.TryGetValue(login, out cached))
                {
                    lock (_cached)
                    {
                        if (!_cached.TryGetValue(login, out cached))
                        {
                            cached = new PagesAuthorized();
                            foreach (var i in _urlReq)
                            {
                                bool allowed = Auth.Check(i.Value.Item1);
                                foreach (var p in i.Value.Item2)
                                    cached.Pages.Add(p, Tuple.Create(allowed, i.Value.Item1));
                                cached.Urls.Add(i.Key, allowed);
                                cached.AbsoluteUrls.Add(new UrlParser(Utils.MakeAbsolutePath(i.Key.CompleteUrl).ToLowerInvariant()), allowed);
                            }
                            foreach (var i in _keyReq)
                            {
                                bool allowed = Auth.Check(i.Value.Item1);
                                foreach (var p in i.Value.Item2)
                                    cached.Pages.Add(p, Tuple.Create(allowed, i.Value.Item1));
                                cached.Keys.Add(i.Key, allowed);
                            }
                            foreach (var i in _pageReq)
                            {
                                bool allowed = Auth.Check(i.Value);
                                cached.Pages.Add(i.Key, Tuple.Create(allowed, i.Value));
                            }
                            _cached.Add(login, cached);
                        }
                    }
                }
                return cached;
            }
        }

        #endregion

        #region private function

        private static void AddUrl(Pages? page, string url, AuthRequirements required)
        {
            UrlParser up = new UrlParser(url.ToLowerInvariant());
            Tuple<AuthRequirements, HashSet<Pages>> r;
            if (_urlReq.TryGetValue(up, out r))
            {
                if (page != null)
                    r.Item2.Add(page.Value);
                //r.Item1.Or(required);
            }
            else
            {
                HashSet<Pages> pages = new HashSet<Pages>();
                if (page != null)
                    pages.Add(page.Value);
                _urlReq[up] = Tuple.Create(required, pages);
            }
        }

        private static void AddKey(Pages? page, string key, AuthRequirements required)
        {
            Tuple<AuthRequirements, HashSet<Pages>> r;
            if (_keyReq.TryGetValue(key, out r))
            {
                if (page != null)
                    r.Item2.Add(page.Value);
                //r.Item1.Or(required);
            }
            else
            {
                HashSet<Pages> pages = new HashSet<Pages>();
                if (page != null)
                    pages.Add(page.Value);
                _keyReq[key] = Tuple.Create(required, pages);
            }
        }

        private static void AddPage(Pages page, AuthRequirements required)
        {
            AuthRequirements r;
            //if (_pageReq.TryGetValue(page, out r))
            //    r.Or(required);
            //else
                _pageReq[page] = required;
        }

        #endregion
    }
}